package com.zz.ecommerce.utils;

import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.CollectionUtils;
import org.xml.sax.SAXException;

import javax.xml.parsers.ParserConfigurationException;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * Map与xml转换工具类
 * by zhangmeng
 */
public class XmlMapUtil {

    private final static Logger logger = LoggerFactory.getLogger(XmlMapUtil.class);

    /**
     * 字符串转map
     *
     * @param xml
     * @return
     * @throws DocumentException
     */
    public static Map xml2map(String xml) throws DocumentException {
        Document doc = DocumentHelper.parseText(xml);
        Element rootElement = doc.getRootElement();
        return ele2map(rootElement);
    }

    /***
     * dom元素转map
     *
     * @param srcElement
     */
    public static Map ele2map(Element srcElement) {
        Map map = new HashMap();
        if (0 == srcElement.elements().size()) {
            map.put(srcElement.getName(), srcElement.getTextTrim());
        } else {
            Map elementsMap = new HashMap();
            List<Element> elements = srcElement.elements();
            if (!CollectionUtils.isEmpty(elements)) {
                for (Element ele : elements) {
                    Object o = elementsMap.get(ele.getName());
                    if (null == o) {
                        elementsMap.putAll(procOneEle(ele));
                    } else {
                        if (!(o instanceof List)) {
                            List list = new ArrayList();
                            list.add(elementsMap.get(ele.getName()));
                            elementsMap.put(ele.getName(), list);
                        }
                        ((List) elementsMap.get(ele.getName())).add(ele2map(ele).get(ele.getName()));
                    }
                }

            }
            map.put(srcElement.getName(), elementsMap);
        }
        return map;
    }

    /**
     * 处理一个元素
     *
     * @param ele
     * @return
     */
    private static Map procOneEle(Element ele) {
        Map map = new HashMap();
        if (ele.elements().size() == 0) {
            map.put(ele.getName(), ele.getTextTrim());
        } else {
            map.putAll(ele2map(ele));
        }
        return map;
    }

    /**
     * 读取xml报文放入map
     *
     * @param in
     * @return
     * @throws ParserConfigurationException
     * @throws SAXException
     * @throws IOException
     */
    public static Map<String, Object> readXml(InputStream in)
        throws ParserConfigurationException, SAXException, IOException, DocumentException {
        Map<String, Object> rtnMap = new HashMap<String, Object>();
        rtnMap = XmlMapUtil.xml2map(inputStream2String(in));
        return rtnMap;
    }

    /**
     * input 转字符串
     *
     * @param in
     * @return
     * @throws IOException
     */
    public static String inputStream2String(InputStream in) throws IOException {
        BufferedReader reader = new BufferedReader(new InputStreamReader(in,
                                                                         "UTF-8"));

        StringBuffer out = new StringBuffer();
        char[] b = new char[4096];
        for (int n; (n = reader.read(b)) != -1; ) {
            out.append(new String(b, 0, n));
        }
        return out.toString().replaceFirst("[^<]*<","<");
    }

}
